/* CD-ROM low level driver 0.00a /* 80x86-version /* /* Written by V.M.G.van Acht /* (c) 1998 by Octagone /* */ #include "stdio.h" /* prototypes */ void Wait (unsigned int count); unsigned int ReadIDEReg (unsigned int regnum); void WriteIDEReg (unsigned int regnum,unsigned int data); int WriteIDECommand (unsigned int *data,unsigned int devnum); int ReadIDEData (unsigned int *data,unsigned int len); int WriteATAPICommand(unsigned char *data,unsigned int devnum,unsigned int maxlen); int ReadATAPIData (unsigned char *data,unsigned int len); int WriteATAPIData (unsigned char *data,unsigned int len); struct structATAPIError ATAPIError (unsigned char devnum); int PlayAudio (unsigned long startsect,unsigned long endsect,unsigned int devnum); int StopAudio (unsigned int devnum); int PauseAudio (unsigned int OnOff,unsigned int devnum); int SetCDSpeed (unsigned int speed,unsigned int devnum); unsigned long LBA2MSF (unsigned long LBA); unsigned long MSF2LBA (unsigned long MSF); void PrintMSF (unsigned long MSF,int flag); int ReadCDSector (unsigned long sectnum,unsigned char *data,unsigned int len,unsigned int devnum); void PrintText (unsigned int *data,unsigned int len); void PrintFileName (unsigned char *data,unsigned char DOSJolietRomeo); int ReadTOC (unsigned char *data,struct structISOHdr *ISOHdr,unsigned long *DirTable,unsigned int devnum); int ReadISOHdr (unsigned long sector,struct structISOHdr *ISOHdr,unsigned long *DirTable,unsigned int devnum); void ResetInquiry (unsigned long *DirTable,unsigned int devnum); unsigned int SearchDir (unsigned long *DirTable); int Inquiry (unsigned long *DirTable,unsigned char *SourceName,unsigned char *data,unsigned int devnum); int ChangeDirectory (unsigned long *DirTable,unsigned char *SourceName,unsigned int devnum); int ChangeDirectoryUp(unsigned long *DirTable,unsigned int devnum); int OpenFile (unsigned long *DirTable,unsigned char *SourceName,unsigned char *FilePointer,unsigned int devnum); int ReadFileBytes (unsigned char *FilePointer,unsigned int length,unsigned char *data); int NameMatch (unsigned char *SourceName,unsigned char *CheckName,unsigned char DOSJolietRomeo); void CopyBytes (unsigned char *source,unsigned char *dest,unsigned int len); unsigned long Char2Long (unsigned char *bytes); unsigned int Char2Int (unsigned char *bytes); void Int2Char (unsigned int value,unsigned char *bytes); void Long2Char (unsigned long value,unsigned char *bytes); unsigned long Char2LongMSBLSB (unsigned char *bytes); unsigned int Char2IntMSBLSB (unsigned char *bytes); void Int2CharMSBLSB (unsigned int value,unsigned char *bytes); void Long2CharMSBLSB (unsigned long value,unsigned char *bytes); /* structures */ struct structFileTime { unsigned char Year; unsigned char Month; unsigned char Day; unsigned char Hour; unsigned char Minute; unsigned char Second; signed char Greenwich; }; struct structHdrTime { unsigned char Year[4]; unsigned char Month[2]; unsigned char Day[2]; unsigned char Hour[2]; unsigned char Minute[2]; unsigned char Second[2]; unsigned char Hundredth[2]; char Greenwich; }; struct structDirRecord { unsigned char RecordLen; unsigned char ExtAttributeLen; unsigned long LocationExtent; unsigned long DataLen; struct structFileTime DateTime; unsigned char FileFlags; unsigned char FileUnitSize; unsigned char InterleaveGapSize; unsigned int VolumeSequenceNumber; unsigned char FileIdentifierLen; unsigned char FileIdentifier[256]; }; struct structISOHdr { unsigned char StructureVersion; unsigned long VolumeSpaceSize; unsigned int VolumeSetSize; unsigned int VolumeSequenceNumber; unsigned int LogicalBlockSize; unsigned long PathTableSize; unsigned long LocationLPathTable; unsigned long LocationOptionLPathTable; unsigned long LocationMPathTable; unsigned long LocationOptionMPathTable; struct structDirRecord RootDir; unsigned char BootSystemIdentifier[32]; unsigned char BootIdentifier[32]; unsigned char SystemIdentifier[32]; unsigned char VolumeIdentifier[32]; unsigned char VolumeSetIdentifier[128]; unsigned char PublisherIdentifier[128]; unsigned char PreparerIdentifier[128]; unsigned char ApplicationIdentifier[128]; unsigned char CopyrightIdentifier[37]; unsigned char AbstractIdentifier[37]; unsigned char BibliographicIdentifier[37]; struct structHdrTime CreationDateTime; struct structHdrTime ModificationDateTime; struct structHdrTime ExpirationDateTime; struct structHdrTime EffectiveDateTime; unsigned char DOSJolietRomeo; /* 0x00=DOS 0x40=Joliet UCS-2 level 1 0x43=Joliet UCS-2 level 2 0x45=Joliet UCS-2 level 3 */ }; struct structCache { unsigned char DeviceNumber; unsigned long SectorNumber; unsigned char SectorCount; unsigned char *MemoryLocation; }; struct structATAPIErrorText { unsigned char ErrorNumber; unsigned char ErrorSubNumber; unsigned char SolutionNumber; /* 0=no solution presented 1=do not consider as error 2=continue 3=retry 4=reset & retry 5=fail & continu 6=user intervention & retry 7=fail, user intervention & continue 8=ask user 9=abort ff=software failure */ unsigned char SolutionSubNumber; /* Solutionnumber.SolutionSubNumber 0. 1. 2. 3. 4. 5.0=fail & continu (on next LogicalBlock) 5.1=fail & continu (on next LogicalSector) 5.2=fail & continu (on next file) 6. 7. 8. 9. ff.0=ATAPI device failure ff.1=Host failure */ unsigned char Text[25]; }; struct structATAPIError { unsigned char Flag; /* Flag 76543210 xxxxxxx0=no error xxxxxxx1=error xxxxxx0x=pointer valid xxxxxx1x=pointer not valid xxxxx0xx=sense key valid xxxxx1xx=sense key not valid xxxx0xxx=current error xxxx1xxx=deferred error Pointer to ErrorText */ unsigned char SenseKey; unsigned char AdditionalSenseKey; unsigned char AdditionalSenseKeyQualifier; unsigned char SolutionNumber; unsigned char SolutionSubNumber; struct structATAPIErrorText *Text; }; struct structCDPosition { unsigned long Absolute; unsigned long Relative; unsigned char Track; unsigned char Index; }; struct structCDNumber { int Flag; /* 0:number=valid 1:number=not valid -1:hardware error */ unsigned char Number[14]; }; /* declarations */ const unsigned int IDEport=0X170, /* IDE port 0=0x1F0, 1=0x170 */ IDERegData=0, /* number of IDE registers */ IDERegError=1, IDERegFeature=1, IDERegSectCount=2, IDERegSectNum=3, IDERegCylLow=4, IDERegCylHigh=5, IDERegDevHead=6, IDERegStatus=7, IDERegCommand=7, IDERegAltStatus=14, IDERegAdres=15; const struct structATAPIErrorText ATAPIErrorText[]= { {0x00,0x00,0,0,"No additional info "}, {0x00,0x11,1,0,"Audio play in progress "}, {0x00,0x12,1,0,"Audio play paused "}, {0x00,0x13,1,0,"Audio play completed "}, {0x00,0x14,9,0,"Audio play error "}, {0x00,0x15,1,0,"No audio play status "}, {0x01,0x00,9,0,"Mechanical error "}, {0x02,0x00,0,0,"No seek complete "}, {0x04,0x00,8,0,"Not ready "}, {0x04,0x01,1,0,"Not ready, in progress.."}, {0x04,0x02,4,0,"Not ready, reinitialize "}, {0x04,0x03,6,0,"Not ready, manual interv"}, {0x04,0x04,1,0,"Not ready, formatting "}, {0x05,0x00,0,0,"No response to selection"}, {0x05,0x01,9,0,"Load/eject failure "}, {0x06,0x00,9,0,"No reference position "}, {0x08,0x00,9,0,"Communication failure "}, {0x08,0x01,9,0,"Communication timed out "}, {0x08,0x02,9,0,"Communication bad parity"}, {0x09,0x00,3,0,"Tracking error "}, {0x09,0x01,8,0,"Tracking servo failure "}, {0x09,0x02,8,0,"Focus servo failure "}, {0x09,0x03,8,0,"Spindle servo failure "}, {0x11,0x00,3,0,"Unrecovered read error "}, {0x11,0x06,3,0,"CIRC unrecovered error "}, {0x15,0x00,3,0,"Random position error "}, {0x15,0x01,8,0,"Mechanical error "}, {0x15,0x02,3,0,"Random position error "}, {0x17,0x00,1,0,"Recovered, no correction"}, {0x17,0x01,1,0,"Recovered, retries "}, {0x17,0x02,1,0,"Recovered, + head offset"}, {0x17,0x03,1,0,"Recovered, - head offset"}, {0x17,0x04,1,0,"Recovered, retries/CIRC "}, {0x17,0x05,1,0,"Recovered, previous ID "}, {0x18,0x00,1,0,"Recovered, correction "}, {0x18,0x01,1,0,"Recovered, reties/correc"}, {0x18,0x02,1,0,"Recovered, auto realloc "}, {0x18,0x03,1,0,"Recovered, CIRC "}, {0x18,0x04,1,0,"Recovered, L-EC "}, {0x1A,0x00,0xFF,1,"Bad parameterlist length"}, {0x20,0x00,0xFF,1,"Invalid command "}, {0x21,0x00,0xFF,1,"Bad logical block number"}, {0x24,0x00,0xFF,1,"Invalid field in packet "}, {0x25,0x00,0,0,"No logical unit support "}, {0x26,0x00,0xFF,1,"Invalid field in paramet"}, {0x26,0x01,0xFF,1,"Parameter not supported "}, {0x26,0x02,0xFF,1,"Bad parameter value "}, {0x28,0x00,0,0,"Medium may have changed "}, {0x29,0x00,1,0,"Reset occured "}, {0x2A,0x00,1,0,"Parameters changed "}, {0x2A,0x01,1,0,"Mode parameters changed "}, {0x30,0x00,8,0,"Incompatible medium "}, {0x30,0x01,8,0,"Unknown format medium "}, {0x30,0x02,8,0,"Incompatible format "}, {0x39,0x00,9,0,"No saving support "}, {0x3A,0x00,1,0,"No medium "}, {0x3A,0x01,1,0,"No medium, tray closed "}, {0x3A,0x02,1,0,"No medium, tray opened "}, {0x3E,0x00,1,0,"Not self-configured yet "}, {0x3F,0x00,1,0,"Operate condition change"}, {0x3F,0x01,1,0,"Microcode changed "}, {0x3F,0x03,1,0,"Inquiry data changed "}, {0x40,0xFF,0xFF,0,"Self test failed "}, {0x44,0x00,0xFF,0,"Internal error "}, {0x4C,0x00,0xFF,0,"Failed self-config "}, {0x4E,0x00,0xFF,1,"Overlap command attempt "}, {0x53,0x00,9,0,"Load/eject failure "}, {0x53,0x02,0,0,"Medium removal prevented"}, {0x57,0x00,8,0,"TOC load error "}, {0x5A,0x00,0,0,"Operator request "}, {0x5A,0x01,0,0,"Medium removal request "}, {0x63,0x00,0xFF,1,"End of user area error "}, {0x64,0x00,0xFF,1,"Illegal track mode "}, {0xB9,0x00,0,0,"Audio play aborted "}, {0xBF,0x00,3,0,"Loss of streaming "}, {0xFF,0xFF,0,0," "} }; /* 123456789012345678901234567890 /* global variables */ unsigned int IDENop [6] ={0,0,0,0,0xA0,0X00}, IDEATAPIReset [6] ={0,0,0,0,0XA0,0X08}, IDEDiagnostic [6] ={0,0,0,0,0XA0,0X90}, IDEATAPIPacket[6] ={0,0,0,0,0XA0,0XA0}, IDEATAPIIdent [6] ={0,0,0,0,0XA0,0XA1}, IDEStandbyImm [6] ={0,0,0,0,0XA0,0XE0}, IDEIdleImm [6] ={0,0,0,0,0XA0,0XE1}, IDECheckpower [6] ={0,0,0,0,0XA0,0XE5}, IDESleep [6] ={0,0,0,0,0XA0,0XE6}, IDESetFeatures[6] ={0,0,0,0,0XA0,0XEF}; unsigned char ATAPIRequestSense[12]={0X03,0,0,0,18,0,0,0,0,0,0,0}, ATAPIStartStopUnit[12]={0X1B,1,0,0,0,0,0,0,0,0,0,0}, ATAPIRead10 [12]={0X28,0,0,0,0,0,0,0,0,0,0,0}, ATAPIReadSubChan1[12]={0X42,0,0x40,1,0,0,0,0,16,0,0,0}, ATAPIReadSubChan2[12]={0x42,0,0x40,2,0,0,0,0,24,0,0,0}, ATAPIReadSubChan3[12]={0x42,0,0x40,3,0,0,0,0,24,0,0,0}, ATAPIReadTOC [12]={0X43,0,0,0,0,0,0,0X03,0X24,0,0,0}, ATAPIPlayAudioMSF[12]={0X47,0,0,0,0,0,0,0,0,0,0,0}, ATAPIPauseAudio [12]={0X4B,0,0,0,0,0,0,0,0,0,0,0}, ATAPIStopAudio [12]={0X4E,0,0,0,0,0,0,0,0,0,0,0}, ATAPISetSpeed [12]={0XBB,0,0,0,0,0,0,0,0,0,0,0}; struct structCache SectorCache; /* SectorBuffer Cache */ unsigned int Device0Data[256], /* Table for device data for dev0 */ Device1Data[256]; /* Table for device data for dev1 */ unsigned char Device0TOC[804], /* Table for device 0 TOC */ Device1TOC[804], /* Table for device 1 TOC */ SectorBuf[2048]; /* Temporary buffer */ struct structISOHdr Device0ISOHdr; /*Table for device 0 ISO header */ struct structISOHdr Device1ISOHdr; /*Table for device 1 ISO header */ unsigned long Device0DirTable[36], /* Table with Sectornumbers of Dirs WARNING: SECTOR numbers not Logical Block Numbers !!! +32=current sectornumber current dir +33=current length current dir +34=current byte counter current dir +35=DOSJolietRomeo +36=Logical Block Size */ Device1DirTable[36]; /* Table with Sectornumbers of Dirs */ unsigned int NumDevice; /************************************************************************/ void Test (unsigned char *ATAPICommand) { unsigned int i; for (i=0;i<12;i++) { printf("%X-",*(ATAPICommand+i)); } } void PrintLong (unsigned long var) { printf("%X",var>>16); printf("%X",var&0xFFFF); } void Wait (unsigned int counter) /* Wait */ { unsigned int i; while (counter>0) {counter--; i=0Xffff; while (i!=0) {i--;} } } unsigned char WaitKey () /* Wait for a key press in: nothing out: key */ { unsigned int i; printf("\nPress any key to continu..."); while ((i=getch())==EOF) {} return(i); } unsigned int ReadIDEReg (unsigned int regnum) /* Read value of IDE register (LOW-LEVEL) in: number of register: 0=data register (16 bit) 1=error register 2=sector count register 3=sector number register 4=cylinder register (LSB) 5=cylinder register (MSB) 6=drive/head register 7=status register 8=Not used 9=not used 10=not used 11=not used 12=not used 13=not used 14=alternate status register 15=adres register out:value */ { unsigned int i,j; if (regnum>=8) {i=IDEport+regnum+0X1F8;} else {i=IDEport+regnum;} asm { MOV DX,(i) IN AX,DX MOV (j),AX } return(j); } void WriteIDEReg (unsigned int regnum, unsigned int data) /* Write value to IDE register (LOW-LEVEL) in: number of register: 0=data register (16 bit) 1=feature register 2=sector count register 3=sector number register 4=cylinder register (LSB) 5=cylinder register (MSB) 6=drive/head register 7=command register 8=Not used 9=not used 10=not used 11=not used 12=not used 13=not used 14=control register 15=not used data */ { unsigned int i,j; if (regnum>=8) {i=IDEport+regnum+0X1F8;} else {i=IDEport+regnum;} j=data; asm { MOV DX,(i) MOV AX,(j) OUT DX,AX } } int WriteIDECommand (unsigned int *data,unsigned int devnum) /* Write IDE Command in: data = pointer to 6 unsigned int with values for reg 2-reg7 devnum = device number 0/1 out: 0 = OK -1 = error */ { unsigned int i,j; i=0; do { if (i==0XFFFF) { return(-1); } i++; } while ((ReadIDEReg(IDERegStatus)&0X80)!=0); WriteIDEReg(IDERegDevHead,(*(data+4)+(devnum<<4))); i=0; do { if (i==0XFFFF) { return(-1); } i++; } while ((ReadIDEReg(IDERegStatus)&0XC0)!=0X40); for (i=0;i<4;i++) { WriteIDEReg(i+2,*(data+i)); } WriteIDEReg(IDERegCommand,*(data+5)); return(0); } int ReadIDEData (unsigned int *data,unsigned int len) /* Read IDE (16 bit) data from data-register in: *data = pointer where data is to be located len = maximum number of words out: -1 = error 0 = OK */ { unsigned int i,j; i=0; do { if (i==0XFFFF) { return(-1); } if ((ReadIDEReg(7)&0x01)!=0) { return(-1);}; } while ((ReadIDEReg(7)&0x80)!=0); if ((ReadIDEReg(7)&0x08)!=0x08) { return(-1); } while (len!=0) { *data=ReadIDEReg(0); len--; data++; } return(0); } int WriteATAPICommand(unsigned char *data,unsigned int devnum,unsigned int maxlen) /* Write ATAPI Command in: *data = pointer to unsigned char array [12] with command arguments MaxLen = maximum number of bytes to be transfered in 1 time (0xffff allowed) DriveNum = drive number 0/1 out: -1 = error 0 = OK */ { unsigned int i; i=0; do { if (i==0XFFFF) { return(-1); } i++; } while ((ReadIDEReg(IDERegStatus)&0X80)!=0); WriteIDEReg(IDERegDevHead,(0XA0+(devnum<<4))); i=0; do { if (i==0XFFFF) { return(-1); } i++; } while ((ReadIDEReg(IDERegStatus)&0X80)!=0); WriteIDEReg(IDERegCylLow,maxlen&0XFF); WriteIDEReg(IDERegCylHigh,maxlen>>8); WriteIDEReg(IDERegCommand,0XA0); i=0; do { if (i==0XFFFF) { return(-1); } if ((ReadIDEReg(IDERegStatus)&0x01)!=0) { return(-1); } } while ((ReadIDEReg(IDERegStatus)&0x08)==0); for (i=1;i<=6;i++) { WriteIDEReg(IDERegData,*(data+0)+(*(data+1)<<8)); data=data+2; } return(0); } int ReadATAPIData (unsigned char *data,unsigned int len) /* Read ATAPI data from data-register to CHAR array in: *data = pointer to unsigned char array where data is to be located len = number of WORDS out: -1 = error 0 = OK */ { unsigned int i,j,k; i=0; do { if (i==0XFFFF) { return(len); } if ((ReadIDEReg(IDERegStatus)&0x01)!=0) { return(-1); } i++; } while ((ReadIDEReg(IDERegStatus)&0x08)==0); do { k=(ReadIDEReg(4)&0XFF)+((ReadIDEReg(5)&0XFF)<<8); do { if (len==0) { return(0); } i=ReadIDEReg(IDERegData); *data=i&0xff; data++; *data=i>>8; len--; k--; data++; } while (k!=0); } while ((ReadIDEReg(IDERegStatus)&0X08)!=0); return(0); } int WriteATAPIData (unsigned char *data,unsigned int len) /* Write ATAPI data to data-register to CHAR array in: *data = pointer to unsigned char array with data len = number of WORDS to write out: -1 = error 0 = OK */ { unsigned int i,j,k; i=0; do { if (i==0) { return(len); } if ((ReadIDEReg(IDERegStatus)&0x01)!=0) { return(-1); } i++; } while ((ReadIDEReg(IDERegStatus)&0x08)==0); do { k=(ReadIDEReg(4)&0XFF)+((ReadIDEReg(5)&0XFF)<<8); do { if (len==0) { return(0); } WriteIDEReg(IDERegData,*data+(*(data+1)<<8)); len--; k--; data=data+2; } while (k!=0); } while ((ReadIDEReg(IDERegStatus)&0X08)!=0); return(0); } struct structATAPIError ATAPIError (unsigned char devnum) /* Check if there is an ATAPI-error pending in: devnum = device number 0/1 out: structATAPIError = Flag 76543210 xxxxxxx0=no error xxxxxxx1=error xxxxxx0x=pointer valid xxxxxx1x=pointer not valid xxxxx0xx=sense key valid xxxxx1xx=sense key not valid xxxx0xxx=current error xxxx1xxx=deferred error SenseKey AdditionalSenseKey AdditionalSenseKeyQualifier Pointer to ErrorText */ { unsigned int i; unsigned char temp[256],*j; struct structATAPIError ReturnValue; ReturnValue.Flag=0x07; i=0; do { if (i==0XFFFF) { return(ReturnValue); } i++; } while ((ReadIDEReg(IDERegStatus)&0X80)!=0); WriteIDEReg(IDERegDevHead,(0XA0+(devnum<<4))); i=0; do { if (i==0XFFFF) { return(ReturnValue); } i++; } while ((ReadIDEReg(IDERegStatus)&0X80)!=0); ReturnValue.Flag=ReturnValue.Flag&(ReadIDEReg(IDERegStatus)&0x01); WriteATAPICommand(ATAPIRequestSense,devnum,128); if (ReadATAPIData(temp,128)==0) { ReturnValue.Flag=ReturnValue.Flag&0xfb; ReturnValue.Flag=ReturnValue.Flag|(*(temp+2)>>2); ReturnValue.SenseKey=*(temp+2)&0x0f; ReturnValue.AdditionalSenseKey=*(temp+12); ReturnValue.AdditionalSenseKeyQualifier=*(temp+13); for (j=ATAPIErrorText;((*j!=0xff) || (*(j+1)!=0xff));j=j+29) { if ((*j==ReturnValue.AdditionalSenseKey) && (*(j+1)==ReturnValue.AdditionalSenseKeyQualifier)) { ReturnValue.Flag=ReturnValue.Flag&0xfd; ReturnValue.SolutionNumber=*(j+2); ReturnValue.SolutionSubNumber=*(j+3); ReturnValue.Text=j+4; return(ReturnValue); } } } return(ReturnValue); } int PlayAudio (unsigned long startsect,unsigned long endsect,unsigned int devnum) /* Play Audio in: startsect = start sector (logical block) endsect = end sector (logical block) devnum = device number 0/1 out: 0 = OK -1 = error */ { unsigned long i; i=LBA2MSF(startsect); ATAPIPlayAudioMSF[3] = (i&0x00ff0000)>>16; ATAPIPlayAudioMSF[4] = (i&0x0000ff00)>>8; ATAPIPlayAudioMSF[5] = (i&0x000000ff); i=LBA2MSF(endsect); ATAPIPlayAudioMSF[6] = (i&0x00ff0000)>>16; ATAPIPlayAudioMSF[7] = (i&0x0000ff00)>>8; ATAPIPlayAudioMSF[8] = (i&0x000000ff); return(WriteATAPICommand(ATAPIPlayAudioMSF,devnum,0XFFFF)); } int StopAudio (unsigned int devnum) /* Stop Audio in: devnum = device number 0/1 out: 0 = OK -1 = error */ { return(WriteATAPICommand(ATAPIStopAudio,devnum,0XFFFF)); } int PauseAudio (unsigned int OnOff,unsigned int devnum) /* Pause Audio in: OnOff 0 = pause 1 = resume devnum = device number 0/1 out: 0 = OK -1 = error */ { ATAPIPauseAudio[8]=OnOff&0x01; return(WriteATAPICommand(ATAPIPauseAudio,devnum,0XFFFF)); } int SetCDSpeed (unsigned int speed,unsigned int devnum) /* Set CD Speed in: speed = speed in Kbyte/sec 0xFFFF = fastest devnum = device number 0/1 out: 0 = OK -1 = error */ { Int2CharMSBLSB(speed,ATAPISetSpeed+2); return(WriteATAPICommand(ATAPISetSpeed,devnum,0XFFFF)); } int StartStopUnit (unsigned int action,unsigned int devnum) /* Start CD spindle servo, Stop CD spindle servo, Open tray, Close tray in: action 0 = Stop spindle servo 1 = Start spindle servo 2 = Open tray 3 = Close tray devnum = device number 0/1 out: 0 = OK -1 = error */ { ATAPIStartStopUnit[4]=action&0x03; return(WriteATAPICommand(ATAPIStartStopUnit,devnum,0XFFFF)); } struct structCDPosition ReadCDPosition (unsigned int devnum) /* Read from Sub-channel data current audio-play-position in: devnum = device number 0/1 out: structCDPos, if .Absolute=0xffffffff then error */ { unsigned char temp[16]; struct structCDPosition CDPos; CDPos.Absolute=0xffffffff; if (WriteATAPICommand(ATAPIReadSubChan1,devnum,16)!=0) { return(CDPos); } if (ReadATAPIData(temp,8)!=0) { return(CDPos); } CDPos.Absolute =Char2LongMSBLSB(temp+8); CDPos.Relative =Char2LongMSBLSB(temp+12); CDPos.Track =*(temp+6); CDPos.Index =*(temp+7); return(CDPos); } struct structCDNumber ReadUPC (unsigned int devnum) /* Read from Sub-channel data current Media Catalog Number in: devnum = device number 0/1 out: structCDNumber, if .Flag=-1 then hardware error */ { unsigned int i; unsigned char temp[24]; struct structCDNumber CDNum; CDNum.Flag=-1; if (WriteATAPICommand(ATAPIReadSubChan2,devnum,24)!=0) { return(CDNum); } if (ReadATAPIData(temp,12)!=0) { return(CDNum); } CDNum.Flag=(*(temp+8)>>7)^0x01; for (i=0;i<=13;i++) { CDNum.Number[i]=*(temp+i+9); } return(CDNum); } struct structCDNumber ReadISRC (unsigned int track,unsigned int devnum) /* Read from Sub-channel data track international standard recording code in: track = tracknumber devnum = device number 0/1 out: structCDNumber, if .Flag=-1 then hardware error */ { unsigned int i; unsigned char temp[24]; struct structCDNumber CDNum; CDNum.Flag=-1; ATAPIReadSubChan3[6]=track; if (WriteATAPICommand(ATAPIReadSubChan3,devnum,24)!=0) { return(CDNum); } if (ReadATAPIData(temp,12)!=0) { return(CDNum); } CDNum.Flag=(*(temp+8)>>7)^0x01; for (i=0;i<=13;i++) { CDNum.Number[i]=*(temp+i+9); } return(CDNum); } unsigned long LBA2MSF (unsigned long LBA) /* convert LBA to MSF in: LBA = unsigned long LBA number out: MSF = unsigned long, bit 0- 7:F bit 8-15:S bit16-23:M */ { unsigned long i,j; LBA=LBA+150; i=(LBA/4500); LBA=LBA-(i*4500); i=i*0x10000; j=(LBA/75); LBA=LBA-(j*75); i=i+(j*0x100)+LBA; return(i); } unsigned long MSF2LBA (unsigned long MSF) /* convert MSF to LBA in: MSF = unsigned long MSF, bit 0- 7:F bit 8-15:S bit16-23:M out: LBA */ { unsigned long i; i=((MSF&0xff0000)>>16)*4500+ ((MSF&0x00ff00)>> 8)*75 + (MSF&0x0000ff); i=i-150; return(i); } void PrintMSF (unsigned long MSF,int flag) /* print MSF in: MSF = unsigned long, bit 0- 7:F bit 8-15:S bit16-23:M flag = 0:print F !=0:do not print F */ { printf("%.2d", (MSF&0xff0000)>>16); printf(":%.2d",(MSF&0x00ff00)>>8); if (flag==0) { printf(":%.2d",(MSF&0x0000ff)); } } int ReadCDSector (unsigned long sectnum,unsigned char *data,unsigned int sectcount,unsigned int devnum) /* Read data-sectors from CD !!!! includes cacheing !!!! in: sectnum = start sector number to be read data = pointer to CHAR where data is to be written sectcount= number of sectors to be read devnum = device number 0/1 out: 0 = OK -1 = error */ { unsigned long i; if ( (SectorCache.DeviceNumber==devnum) && (SectorCache.SectorNumber==sectnum) && (SectorCache.MemoryLocation==data) && (sectcount==1) && (SectorCache.SectorCount==1) ) { return(0); } Long2CharMSBLSB(sectnum,ATAPIRead10+2); Int2CharMSBLSB(sectcount,ATAPIRead10+7); if (WriteATAPICommand(ATAPIRead10,devnum,0XFFFF)!=0) { return(-1); } i=0; do { if (i==0x0FFFFFF) { printf("Duurt te lang"); return(-1); } i++; } while ((ReadIDEReg(IDERegStatus)&0X80)!=0); if (ReadATAPIData(data,sectcount<<10)!=0) { return(-1); } SectorCache.DeviceNumber=devnum; SectorCache.SectorNumber=sectnum; SectorCache.MemoryLocation=data; SectorCache.SectorCount=sectcount; return(0); } void PrintText (unsigned int *data,unsigned int len) /* Print ASCII-characters in words in: *data = pointer to words with 2 ASCII characters in each len = number of words (=Number of characters/2) */ { unsigned int i; for (i=0;i>8,(*(data+i))&0xff);}; } void PrintFileName (unsigned char *data,unsigned char DOSJolietRomeo) /* Print a filename, DOS 8.3 (ISO9660 extended to 32 characters), Joliet, Romeo in: *data = pointer to filename. First char gives length DOSJolietRomeo = DOSJolietRomeo flag */ { unsigned int i; for (i=1;i<=*(data);) { if (DOSJolietRomeo==0) { if (*(data+i)==0x3B) { return; } printf("%c",*(data+i)); i++; } else if ( (DOSJolietRomeo==0x40) || (DOSJolietRomeo==0x43) || (DOSJolietRomeo==0x45) ) { if ( (*(data+i))==0x00 || (*(data+i+1))==0x3B ) { return; } printf("%c",*(data+i+1)); i++; i++; } /* else if hier moet nog Romeo-code staan $#@!$#! */ } } int ReadTOC (unsigned char *data,struct structISOHdr *ISOHdr,unsigned long *DirTable,unsigned int devnum) /* Read TOC of a CD, and ISO9660 data in: *data = pointer to dataspace (max 804 bytes) *ISOdata= pointer to ISO-data devnum = device number out: -1 = error 0 = OK, no data tracks 1 = OK, 1 track (data track) >1 = OK, datatracks, more than 1 track (mixed mode?) */ { unsigned int i,datatrack=0; unsigned long adres; unsigned char *j; if (WriteATAPICommand(ATAPIReadTOC,devnum,0XFFFF)!=0) { return(-1); } if (ReadATAPIData(data,804)!=0) { return(-1); } for (i=*(data+2);i<=(data+3);i++) { if ((*(data+(i-*(data+2))*8+5)&0X0D)==0X04) { if (datatrack==0) { j=data+(i-*(data+2))*8+8; adres=(*(j+0)<<24) + (*(j+1)<<16) + (*(j+2)<<8) + (*(j+3)); ReadISOHdr(adres,ISOHdr,DirTable,devnum); } datatrack=i; } } return(datatrack); } int ReadISOHdr (unsigned long sector,struct structISOHdr *ISOHdr,unsigned long *DirTable,unsigned int devnum) /* Fill ISOHdr in: sector = first sector of ISO9660 data-block data = pointer to where ISOHdr is to be located devnum = device number 0/1 out: 0 = OK (ISO9660 disc) -1 = error (not ISO9660 disc) */ { unsigned long cursect; unsigned int i; cursect=sector+16; do { ReadCDSector(cursect,SectorBuf,1,devnum); if (*(SectorBuf+1)!='C' || *(SectorBuf+2)!='D' || *(SectorBuf+3)!='0' || *(SectorBuf+4)!='0' || *(SectorBuf+5)!='1' ) {return(-1);} switch (*(SectorBuf)) { case 0 : { CopyBytes(SectorBuf+7,ISOHdr->BootSystemIdentifier,32); CopyBytes(SectorBuf+39,ISOHdr->BootIdentifier,32); break; } case 1 : { CopyBytes(SectorBuf+8,&ISOHdr->SystemIdentifier,32); CopyBytes(SectorBuf+40,&ISOHdr->VolumeIdentifier,32); ISOHdr->VolumeSpaceSize =Char2Long(SectorBuf+80); ISOHdr->VolumeSetSize =Char2Int(SectorBuf+120); ISOHdr->VolumeSequenceNumber =Char2Int(SectorBuf+124); ISOHdr->LogicalBlockSize =Char2Int(SectorBuf+128); ISOHdr->PathTableSize =Char2Long(SectorBuf+132); ISOHdr->LocationLPathTable =Char2Long(SectorBuf+140); ISOHdr->LocationOptionLPathTable=Char2Long(SectorBuf+144); ISOHdr->LocationMPathTable =Char2Long(SectorBuf+148); ISOHdr->LocationOptionMPathTable=Char2Long(SectorBuf+152); ISOHdr->RootDir.RecordLen =*(SectorBuf+156); ISOHdr->RootDir.ExtAttributeLen=*(SectorBuf+157); ISOHdr->RootDir.LocationExtent=Char2Long(SectorBuf+158); ISOHdr->RootDir.DataLen =Char2Long(SectorBuf+166); CopyBytes(SectorBuf+174,&ISOHdr->RootDir.DateTime,7); ISOHdr->RootDir.FileFlags =*(SectorBuf+181); ISOHdr->RootDir.FileUnitSize =*(SectorBuf+182); ISOHdr->RootDir.InterleaveGapSize=*(SectorBuf+183); ISOHdr->RootDir.VolumeSequenceNumber=*(SectorBuf+184); ISOHdr->RootDir.FileIdentifierLen=*(SectorBuf+185); CopyBytes(SectorBuf+189,&ISOHdr->RootDir.FileIdentifier,1); CopyBytes(SectorBuf+190,&ISOHdr->VolumeSetIdentifier,128); CopyBytes(SectorBuf+318,&ISOHdr->PublisherIdentifier,128); CopyBytes(SectorBuf+446,&ISOHdr->PreparerIdentifier,128); CopyBytes(SectorBuf+574,&ISOHdr->ApplicationIdentifier,128); CopyBytes(SectorBuf+702,&ISOHdr->CopyrightIdentifier,37); CopyBytes(SectorBuf+739,&ISOHdr->AbstractIdentifier,37); CopyBytes(SectorBuf+776,&ISOHdr->BibliographicIdentifier,37); CopyBytes(SectorBuf+813,&ISOHdr->CreationDateTime,17); CopyBytes(SectorBuf+830,&ISOHdr->ModificationDateTime,17); CopyBytes(SectorBuf+847,&ISOHdr->ExpirationDateTime,17); CopyBytes(SectorBuf+864,&ISOHdr->EffectiveDateTime,17); ISOHdr->StructureVersion=*(SectorBuf+881); ISOHdr->DOSJolietRomeo=0; break; } case 2 : { if ((*(SectorBuf+7)&0x01)==0) { if ( (*(SectorBuf+88)==0x25) && (*(SectorBuf+89)==0x2F) ) { if ( (*(SectorBuf+90)==0x40) || (*(SectorBuf+90)==0x43) || (*(SectorBuf+90)==0x45) ) { CopyBytes(SectorBuf+8,&ISOHdr->SystemIdentifier,32); CopyBytes(SectorBuf+40,&ISOHdr->VolumeIdentifier,32); ISOHdr->VolumeSpaceSize =Char2Long(SectorBuf+80); ISOHdr->VolumeSetSize =Char2Int(SectorBuf+120); ISOHdr->VolumeSequenceNumber =Char2Int(SectorBuf+124); ISOHdr->LogicalBlockSize =Char2Int(SectorBuf+128); ISOHdr->PathTableSize =Char2Long(SectorBuf+132); ISOHdr->LocationLPathTable =Char2Long(SectorBuf+140); ISOHdr->LocationOptionLPathTable=Char2Long(SectorBuf+144); ISOHdr->LocationMPathTable =Char2Long(SectorBuf+148); ISOHdr->LocationOptionMPathTable=Char2Long(SectorBuf+152); ISOHdr->RootDir.RecordLen =*(SectorBuf+156); ISOHdr->RootDir.ExtAttributeLen=*(SectorBuf+157); ISOHdr->RootDir.LocationExtent=Char2Long(SectorBuf+158); ISOHdr->RootDir.DataLen =Char2Long(SectorBuf+166); CopyBytes(SectorBuf+174,&ISOHdr->RootDir.DateTime,7); ISOHdr->RootDir.FileFlags =*(SectorBuf+181); ISOHdr->RootDir.FileUnitSize =*(SectorBuf+182); ISOHdr->RootDir.InterleaveGapSize=*(SectorBuf+183); ISOHdr->RootDir.VolumeSequenceNumber=*(SectorBuf+184); ISOHdr->RootDir.FileIdentifierLen=*(SectorBuf+185); CopyBytes(SectorBuf+189,&ISOHdr->RootDir.FileIdentifier,1); CopyBytes(SectorBuf+190,&ISOHdr->VolumeSetIdentifier,128); CopyBytes(SectorBuf+318,&ISOHdr->PublisherIdentifier,128); CopyBytes(SectorBuf+446,&ISOHdr->PreparerIdentifier,128); CopyBytes(SectorBuf+574,&ISOHdr->ApplicationIdentifier,128); CopyBytes(SectorBuf+702,&ISOHdr->CopyrightIdentifier,37); CopyBytes(SectorBuf+739,&ISOHdr->AbstractIdentifier,37); CopyBytes(SectorBuf+776,&ISOHdr->BibliographicIdentifier,37); CopyBytes(SectorBuf+813,&ISOHdr->CreationDateTime,17); CopyBytes(SectorBuf+830,&ISOHdr->ModificationDateTime,17); CopyBytes(SectorBuf+847,&ISOHdr->ExpirationDateTime,17); CopyBytes(SectorBuf+864,&ISOHdr->EffectiveDateTime,17); ISOHdr->StructureVersion=*(SectorBuf+881); ISOHdr->DOSJolietRomeo=*(SectorBuf+90); } } } break; } case 3 : { break; } case 255 : { break; } default : { return(-1); } } cursect++; } while (*(SectorBuf)!=255); for (i=0;i<34;i++) { *(DirTable+i)=0; } *(DirTable+36)=ISOHdr->LogicalBlockSize; *(DirTable)=(ISOHdr->RootDir.LocationExtent)/(2048/ *(DirTable+36)); *(DirTable+1)=ISOHdr->RootDir.DataLen; *(DirTable+35)=ISOHdr->DOSJolietRomeo; return(0); } unsigned int SearchDir (unsigned long *DirTable) /* Give depth of current directory in DirTable in: DirTable= pointer to Directory Table out: integer of directory depth */ { unsigned int i; i=15; while (*(DirTable+(i<<1))==0) { i--; } return(i); } void ResetInquiry (unsigned long *DirTable,unsigned int devnum) /* Reset Inquiry. Give this command, before the FIRST "next inquiry item" command in: DirTable= pointer to Directory Table devnum = device number 0/1 */ { unsigned int i; i=SearchDir(DirTable); *(DirTable+32)=*(DirTable+(i<<1)); *(DirTable+33)=*(DirTable+(i<<1)+1)-68; *(DirTable+34)=68; } int Inquiry (unsigned long *DirTable,unsigned char *SourceName,unsigned char *data,unsigned int devnum) /* Give next file in inquiry in: DirTable= pointer to Directory Table SourceName=Name to look for. Char array terminated with \0 wildcards: ? = any character * = any number of any characters upto "." \ = from here on don't care data = pointer to data area where directory record is loaded devnum = device number out: 0 = OK, found 1 = error (not found) -1 = error (hardware) */ { unsigned long cursect, curlen, curbyte; cursect=*(DirTable+32); curlen =*(DirTable+33); curbyte=*(DirTable+34); while (curlen!=0) { if (curbyte==512) { curbyte=0; cursect++; } if (ReadCDSector(cursect,SectorBuf,1,devnum)!=0) { return(-1); } if (*(SectorBuf+curbyte)==0) { if (curlen<=(2048-curbyte)) { *(DirTable+33)=0; return(1); } curlen=curlen-(2048-curbyte); curbyte=0; cursect++; ReadCDSector(cursect,SectorBuf,1,devnum); } if (NameMatch(SectorBuf+curbyte+32,SourceName,*(DirTable+35))==0) { CopyBytes(SectorBuf+curbyte,data,*(SectorBuf+curbyte)); *(DirTable+32)=cursect; *(DirTable+33)=curlen-*(SectorBuf+curbyte); *(DirTable+34)=curbyte+*(SectorBuf+curbyte); return(0); } curlen=curlen-*(SectorBuf+curbyte); curbyte=curbyte+*(SectorBuf+curbyte); } *(DirTable+32)=cursect; *(DirTable+33)=curlen; *(DirTable+34)=curbyte; return(1); } int NameMatch (unsigned char *SourceName,unsigned char *CheckName,unsigned char DOSJolietRomeo) /* Check if SourceName and CheckName are equal. CheckName is allowed to have wildcards in: SourceName = char pointer to char array to be checked. FIRST byte L in array is length of name (so length array is L+1) CheckName = pointer to char ASCIIZ text wildcards: ? = any character * = any number of any characters upto "." \ = from here on don't care DOSJolietRomeo = 00 = DOS 8.3 filename in Sourcename 40 = Joliet filename in Sourcename, UCS-2 level 1 43 = Joliet filename in Sourcename, UCS-2 level 2 45 = Joliet filename in Sourcename, UCS-2 level 3 out: 0 = OK (equal) -1 = error (not equal) */ { unsigned int SourceCounter=1, CheckCounter =0; do { if (*(CheckName+CheckCounter)=='\\') { return(0); } if ( ((*SourceName - SourceCounter + 1 )==0) || ( (DOSJolietRomeo==0) && (*(SourceName + SourceCounter)==0x3B) ) || ( ( (DOSJolietRomeo==0x40) || (DOSJolietRomeo==0x43) || (DOSJolietRomeo==0x45) ) && ( (*(SourceName + SourceCounter)==0x00) && (*(SourceName + SourceCounter)==0x3B) )) ) { while (*(CheckName+CheckCounter)!=0) { if ((*(CheckName+CheckCounter)=='*') || (*(CheckName+CheckCounter)=='?') || (*(CheckName+CheckCounter)=='.') || (*(CheckName+CheckCounter)=='\\') ) { CheckCounter++; } else { return(-1); } } return(0); } if (*(CheckName+CheckCounter)==0) { return(-1); } if (*(CheckName+CheckCounter)=='?') { CheckCounter++; if (DOSJolietRomeo==0) { SourceCounter++; } else if ( (DOSJolietRomeo==0x40) || (DOSJolietRomeo==0x43) || (DOSJolietRomeo==0x45) ) { SourceCounter++; SourceCounter++; } /* else if .... hier moet nog een check voor Romeo %$#@#$@!%$ */ } else if (*(CheckName+CheckCounter)=='*') { if (DOSJolietRomeo==0) { while (*(SourceName+SourceCounter)!='.') { SourceCounter++; if ((*SourceName - SourceCounter) == 0) { return(0); } } CheckCounter++; } else if ( (DOSJolietRomeo==0x40) || (DOSJolietRomeo==0x43) || (DOSJolietRomeo==0x45) ) { while (*(SourceName+SourceCounter)!='.') { SourceCounter++; SourceCounter++; if ((*SourceName - SourceCounter) == 0) { return(0); } } CheckCounter++; } /* else if ..... hier moet nog een check voor Romeo !$%#@!$#@ */ } else { if (DOSJolietRomeo==0) { if (*(SourceName+SourceCounter)!= *(CheckName+CheckCounter)) { return (-1); } else { SourceCounter++; CheckCounter++; } } else if ( (DOSJolietRomeo==0x40) || (DOSJolietRomeo==0x43) || (DOSJolietRomeo==0x45) ) { if (*(SourceName+SourceCounter+1)!= *(CheckName+CheckCounter)) { return (-1); } else { SourceCounter++; SourceCounter++; CheckCounter++; } } /* else if hier moet nog een test voor Romeo */ } } while (1); } int ChangeDirectory (unsigned long *DirTable,unsigned char *SourceName,unsigned int devnum) /* Change active directory in: DirTable= pointer to Directory Table SourceName=Name to look for. Char array terminated with \0 wildcards: ? = any character * = any number of any characters upto "." \ = from here on don't care devnum = device number out: 0 = OK, found 1 = error (not found) 2 = error (too deep (>16)) -1 = error (hardware) */ { unsigned char temp[256]; unsigned int i; ResetInquiry(DirTable,devnum); while (1) { i=Inquiry(DirTable,SourceName,temp,devnum); if (i!=0) { return(i); } if ((*(temp+25)&0x02)==0x02) { i=SearchDir(DirTable); if (i==15) { return(2); } i++; *(DirTable+(i<<1))=(Char2Long(temp+2))/(2048/ *(DirTable+36)); *(DirTable+(i<<1)+1)=Char2Long(temp+10); ResetInquiry(DirTable,devnum); return(0); } } } int ChangeDirectoryUp(unsigned long *DirTable,unsigned int devnum) /* Change active directory, one brach up. in: DirTable= pointer to Directory Table devnum = device number out: 0 = OK, found 1 = error (allready in root) */ { unsigned int i; i=SearchDir(DirTable); if (i==0) { return(1); } *(DirTable+(i<<1))=0; *(DirTable+(i<<1)+1)=0; ResetInquiry(DirTable,devnum); return(0); } int OpenFile (unsigned long *DirTable,unsigned char *SourceName,unsigned char *FilePointer,unsigned int devnum) /* Open File in: DirTable= pointer to Directory Table SourceName=Name to look for. Char array terminated with \0 wildcards: ? = any character * = any number of any characters upto "." \ = from here on don't care FilePointer=Char array (274 bytes) +0 = directory entry (256) +256 = current Logical Block (4) +260 = current File length (4) +264 = current byte counter (4) +268 = devnum (1) +269 = Logical Block Length (4) +273 = current File Unit Size counter (1) devnum = device number out: 0 = OK, found 1 = error (not found) -1 = error (hardware) */ { unsigned int i; ResetInquiry(DirTable,devnum); while (1) { i=Inquiry(DirTable,SourceName,FilePointer,devnum); if (i!=0) { return(i); } if ((*(FilePointer+25)&0x02)!=0x02) { CopyBytes(FilePointer+2,FilePointer+256,4); CopyBytes(FilePointer+10,FilePointer+260,4); Long2Char(0,FilePointer+264); *(FilePointer+268)=devnum; Long2Char(*(DirTable+36),FilePointer+269); *(FilePointer+273)=1; return(0); } } } int ReadFileBytes (unsigned char *FilePointer,unsigned int length,unsigned char *data) /* Read from File, in bytes in: FilePointer= pointer to file info table length = number of bytes to be read data = pointer to where data is to be located out: 0 = OK <>0 = error (EOF) number is bytes read -1 = error (hardware) */ { unsigned long curLB, curbyte, curlen, LBL; unsigned int i=0, j; unsigned char devnum; curLB=Char2Long(FilePointer+256); curlen=Char2Long(FilePointer+260); curbyte=Char2Long(FilePointer+264); devnum=*(FilePointer+268); LBL=Char2Long(FilePointer+269); while (length!=0) { if (curlen==0) { return(-1); } if (ReadCDSector(curLB/(2048/LBL),SectorBuf,1,devnum)!=0) { return(-1); } j=(curLB%(2048/LBL))<<9; if (curlen<(LBL-curbyte)) { if (curlen<=length) { CopyBytes(SectorBuf+curbyte+j,data,curlen); i=i+curlen; return(i); } } if (length<(LBL-curbyte)) { CopyBytes(SectorBuf+curbyte+j,data,length); Long2Char(curLB,FilePointer+256); Long2Char(curlen-length,FilePointer+260); Long2Char(curbyte+length,FilePointer+264); return(0); } CopyBytes(SectorBuf+curbyte+j,data,(LBL-curbyte)); if (*(FilePointer+26)==0) { curLB++; } else { if ( *(FilePointer+273) == *(FilePointer+26) ) { *(FilePointer+273)=1; curLB=curLB + *(FilePointer+27) + 1; } else { *(FilePointer+273)=*(FilePointer+273)+1; curLB++; } } curlen=curlen-(LBL-curbyte); length=length-(LBL-curbyte); i=i+(LBL-curbyte); data=data+(LBL-curbyte); curbyte=0; } Long2Char(curLB,FilePointer+256); Long2Char(curlen,FilePointer+260); Long2Char(curbyte,FilePointer+264); return(0); } void CopyBytes (unsigned char *source,unsigned char *dest,unsigned int len) /* copy bytes from source to destination in: *source pointer to source *dest pointer to destination len number of bytes */ { while (len!=0) { *dest=*source; len--; dest++; source++; } } unsigned long Char2Long (unsigned char *bytes) /* convert 4 bytes to 1 long, (LSB----MSB) in: *char pointer to 4 bytes out: value */ { unsigned long j; j = *(bytes+3); j = (j<<8) + *(bytes+2); j = (j<<8) + *(bytes+1); j = (j<<8) + *(bytes+0); return(j); } unsigned long Char2LongMSBLSB (unsigned char *bytes) /* convert 4 bytes to 1 long, (MSB----LSB) in: *char pointer to 4 bytes out: value */ { unsigned long j; j = *(bytes+0); j = (j<<8) + *(bytes+1); j = (j<<8) + *(bytes+2); j = (j<<8) + *(bytes+3); return(j); } unsigned int Char2Int (unsigned char *bytes) /* convert 2 bytes to 1 int, (LSB----MSB) in: *char pointer to 2 bytes out: value */ { return( *(bytes+0) + (*(bytes+1)<<8) ); } unsigned int Char2IntMSBLSB (unsigned char *bytes) /* convert 2 bytes to 1 int, (MSB----LSB) in: *char pointer to 2 bytes out: value */ { return( *(bytes+1) + (*(bytes+0)<<8) ); } void Int2Char (unsigned int value,unsigned char *bytes) { *(bytes )=(value&0x00ff); *(bytes+1)=(value&0xff00)>>8; } void Int2CharMSBLSB (unsigned int value,unsigned char *bytes) { *(bytes+1)=(value&0x00ff); *(bytes )=(value&0xff00)>>8; } void Long2Char (unsigned long value,unsigned char *bytes) { *(bytes )=(value&0x000000ff); *(bytes+1)=(value&0x0000ff00)>>8; *(bytes+2)=(value&0x00ff0000)>>16; *(bytes+3)=(value&0xff000000)>>24; } void Long2CharMSBLSB (unsigned long value,unsigned char *bytes) { *(bytes+3)=(value&0x000000ff); *(bytes+2)=(value&0x0000ff00)>>8; *(bytes+1)=(value&0x00ff0000)>>16; *(bytes )=(value&0xff000000)>>24; } void main () { unsigned int i,j,k; unsigned char temp[512], temp1[512], *test; struct structCDPosition CDPos; struct structCDNumber CDNum; struct structATAPIError error; SectorCache.DeviceNumber=0xff; printf("\nATA v0.10a"); printf("\nATAPI-CDROM v0.10a"); printf("\nATAPI audio-extension v0.00a"); printf("\nISO 9660:1988, level 2 v0.00a"); printf("\nISO 9660:Joliet-extension v0.00a"); printf("\n\nProgrammed by V.M.G. van Acht"); printf("\n(c) 1998 by VVA\n"); if (WriteIDECommand(IDEATAPIIdent,0)==0) { if (ReadIDEData(Device0Data,256)==0) { printf("Device 0: "); PrintText(Device0Data+27,20); printf(" - "); PrintText(Device0Data+23,4); printf("\n"); NumDevice=0; } else { NumDevice=0XFFFF; } } else { NumDevice=0XFFFF; } if (NumDevice==0XFFFF) { printf("ATAPI Device 0 error\n"); return(-1); } if (WriteIDECommand(IDEATAPIIdent,1)==0) { if (ReadIDEData(Device1Data,256)==0) { printf("Device 1: "); PrintText(Device1Data+27,20); printf(" - "); PrintText(Device1Data+23,4); printf("\n"); NumDevice=1; } } ReadTOC(Device0TOC,&Device0ISOHdr,Device0DirTable,0); PlayAudio(40000,100000,0); Wait(3000); printf("\n"); for (i=0;i<0x1000;i++) { CDPos=ReadCDPosition(0); PrintMSF(LBA2MSF(CDPos.Relative),0); printf("\r"); } PauseAudio(0,0); Wait(1000); PauseAudio(1,0); Wait(10000); StopAudio(0); StartStopUnit(2,0); Wait(3000); StartStopUnit(3,0); /* CDROM ResetInquiry(Device0DirTable,0); while (Inquiry(Device0DirTable,"\\",temp,0)==0) { PrintFileName(temp+32,Device0ISOHdr.DOSJolietRomeo); printf("\n"); } printf("\n"); if (ChangeDirectory(Device0DirTable,"BC5\\",0)!=0) { printf("\nChange Dir error"); } ResetInquiry(Device0DirTable,0); j=0; while (j<7 && Inquiry(Device0DirTable,"\\",temp,0)==0) { PrintFileName(temp+32,Device0ISOHdr.DOSJolietRomeo); printf("\n"); j++; } printf("\n"); /* if (ChangeDirectoryUp(Device0DirTable,0)!=0) { printf("\nChange Dir error"); } ResetInquiry(Device0DirTable,0); j=0; while (j<15 && Inquiry(Device0DirTable,"\\",temp,0)==0) { for (i=33;i<(33+temp[32]);i++) { printf("%c",temp[i]); } printf("\n"); j++; } */ /* CR-ROM if (OpenFile(Device0DirTable,"V*.TXT",temp,0)!=0) { printf("Open error"); } else { while ((i=ReadFileBytes(temp,5,temp1))==0) { for (i=0;i<5;i++) { printf("%c",temp1[i]); } } if (i!=-1) { for (j=0;i!=0;i--,j++) { printf("%c",temp1[j]); } } } WaitKey(); error=ATAPIError(0); printf("\nFlag:%X",error.Flag); printf("\nText:%s",error.Text); */ }